iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 25
2
Modern Web

初探Vue.js 30天系列 第 25

[Day 25] Vue.js - 台灣縣市選擇器

  • 分享至 

  • xImage
  •  

今天要來使用laravel+Vue的台灣縣市選擇器

先前準備安裝套件

在開始前請先安裝bootstrapbootstrap-sass,這兩個套件

npm install --save-dev bootstrap@4.0.0
npm install --save-dev bootstrap-sass@3.4.1

新增config

config資料夾,建立country.php,參閱縣市資料(這是待會,會用到的縣市資料結構)

新增Controller

在專案的目錄下,輸入指令新增CountryController.php

php artisan make:controller CountryController

使用country.php

CountryController使用Configcountry.php,拿到縣市選單資料

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Config;

class CountryController extends Controller
{
    public function getCountryData()
    {
        $country = Config::get('country');
        $countryData = [
            'city' => $country['city'],
            'districts' => $country['districts']
        ];

        return view('country', $countryData);
    }
}

設定Routes

routes/web.php路徑底下,新增/country,執行CountryControllergetCountryData

Route::get('/country', 'CountryController@getCountryData');

新增JS檔案

接下來在resources/js資料夾裡新增js檔,檔名為country.js,這裡要引入bootstrap,以及另外兩個components

import 'bootstrap/dist/css/bootstrap.css'
import countryCity from './components/country/City.vue';
import countryDistricts from './components/country/Districts.vue';

let app = new Vue({
    el: '#app',
    data: {
        message: 'Vue練習:',
        showText: '顯示郵遞區號!',
        citySelected: null,
        districtsSelected: null,
        citySelectedText: '',
        districtsSelectedText: '',
        btnStyle: 'btn btn-primary'
    },
    components: {
        'country-city': countryCity,
        'country-districts': countryDistricts
    },
    methods: {
        updateCity(CitySelectedText, CitySelected) {
            this.citySelectedText = CitySelectedText
            this.citySelected = CitySelected
            this.districtsSelected = null
        },
        updateDistricts(DistrictsSelectedText, DistrictsSelected) {
            this.districtsSelectedText = DistrictsSelectedText
            this.districtsSelected = DistrictsSelected
        },
        showPostalCode() {
            let show_text = '請選擇縣市和市區'
            if (this.citySelectedText != '' && this.districtsSelectedText != '' && this.districtsSelected != null) {
                show_text = this.citySelectedText + " " + this.districtsSelectedText + " 郵遞區號為:" + this.districtsSelected 
            }
            alert(show_text)
        }
    }
})

以上範例,updateCity()是從country-city傳進來,更新citySelectedTextcitySelected 這兩個變數值,另一個updateDistricts()是從country-districts傳進來,更新districtsSelectedTextdistrictsSelected另外兩個變數值,showPostalCode()則是將citySelectedTextdistrictsSelectedTextdistrictsSelected 組成字串,用提示訊息的方式顯示在頁面上。

新增components

resources/js/components/country路徑底下,新增兩個component檔案,City.vueDistricts.vue

<!-- City.vue -->
<template>
	<select v-model="cityValue" id="us_city" name="us_city" @change="changeCity()">
		<option value=null disabled selected>--請選擇--</option>
		<option v-for="(city, index) in cityArray" :key="index"
			:value="city.value">{{ city.text }}</option>
	</select>
</template>

<script>
export default {
	props: {
		cityData: {
			type:Array
		},
		citySelected: {
			type:Number
		}
	},
	data() {
		return {
			cityArray: this.cityData,
			cityValue: this.citySelected,
		}
	},
	methods:{
		changeCity() {
			if (this.cityValue != null) {
				this.$emit('change-city', this.cityArray[this.cityValue]['text'], this.cityValue)
			}
		}
	}
}
</script>

City.vue的範例中,props傳進來的cityArray當作縣市選單的資料,以及citySelected當作選單的預設值,當選擇縣市資料時,去觸發changeCity(),使用emit傳遞,function名稱為change-city,將文字value資料傳到country.jsupdateCity()

<!-- Districts.vue -->
<template>
	<select v-model="districtsValue" id="us_districts" name="us_districts" >
		<option value=null disabled selected>--請選擇--</option>
		<option v-for="(districts, index) in districtsArray" :key="index" :value="districts.value">{{ districts.text }}</option>
	</select>
</template>

<script>
export default {
	props: {
		citySelected: {
			type:Number
		},
		districtsData: {
			type:Array
		},
		districtsSelected: {
			type:Number
		}
	},
	computed: {
		districtsArray() {
			if (this.citySelected != null ) {
				this.districtsValue = this.districtsSelected
				return this.districtsData[this.citySelected];
			}
		}
	},
	data() {
		return {
			districts: [],
			districtsValue: this.districtsSelected,
		}
	},
	watch:{
		districtsValue(newVal) {
			let districtsText = ''
			_.findKey (this.districtsArray, (e, key) => {
				 if (e.value === newVal) {
					 districtsText = e.text
				 }
			})

			if (districtsText != '') {
				this.$emit('change-districts', districtsText, newVal)
			}
		}
	}
}
</script>

Districts.vue的範例中,props傳進來的citySelected是目前縣市資料,districtsData是一整包市區資料,districtsSelected為選單的預設值。而districtsArray是縣市資料有更新時,會重新計算市區選單的資料,當選擇市區資料時,因為我們監聽districtsValue變數,當變數值改變時,會使用emit傳遞,function名稱為change-districts,將文字value資料傳到country.jsupdateDistricts()

新增模板頁面

做完之後在resources/views資料夾裡,新增頁面country.blade.php

<html>
	<head>
		<meta name="csrf-token" content="{{ csrf_token() }}">
	</head>

	<body>
		<div id="app">
			@{{ message }}
			<country-city
				@change-city="updateCity" 
				:city-selected="citySelected"
				:city-data="{{ json_encode($city) }}"
			>
			</country-city>
			<country-districts 
				@change-districts="updateDistricts" 
				:city-selected="citySelected" 
				:districts-selected="districtsSelected" 
				:districts-data="{{ json_encode($districts) }}" 
			/>
			</country-districts>
			<input 
				type="button" 
				id="show" 
				:class="btnStyle" 
				:value="showText" 
				@click="showPostalCode" 
			/>
		</div>
		<script src="{{mix('js/app.js')}}"></script>
		<script src="{{mix('js/country.js')}}"></script>
	</body>
</html>

CountryController傳過來的citydistricts資料,以及country.js的值,會傳到另外兩個component

編譯JS檔案

完成之後,我們要進行編譯,請在webpack.mix.js檔案,新增country.js檔案

mix.js('resources/js/app.js', 'public/js')
   .js('resources/js/country.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');

新增完成,執行編譯指令,執行完後會顯示下方的畫面

npm run watch

https://ithelp.ithome.com.tw/upload/images/20201009/20108252hcNs266o6f.png

啟動本機站台

$ php artisan serve
Starting Laravel development server: http://127.0.0.1:8000

啟動之後,輸入網址為http://127.0.0.1:8000/country

操作流程

在頁面上選擇縣市與市區後,點擊按鈕後就會顯示郵遞區號!

基隆市 中山區 郵遞區號為:203

上一篇
[Day 24] Lodash - JS library
下一篇
[Day 26] Vue - axios&vSelect 模糊查詢
系列文
初探Vue.js 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言